// 版权所有2009年围棋作者。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

/*
Package zlib implements reading and writing of zlib format compressed data,
as specified in RFC 1950.

The implementation provides filters that uncompress during reading
and compress during writing.  For example, to write compressed data
to a buffer:

	var b bytes.Buffer
	w := zlib.NewWriter(&b)
	w.Write([]byte("hello, world\n"))
	w.Close()

and to read that data back:

	r, err := zlib.NewReader(&b)
	io.Copy(os.Stdout, r)
	r.Close()
*/
package zlib

import (
	"bufio"
	"compress/flate"
	"errors"
	"hash"
	"hash/adler32"
	"io"
)

const zlibDeflate = 8

var (
	// 读取具有无效校验和的ZLIB数据时返回ErrChecksum。
	ErrChecksum = errors.New("zlib: invalid checksum")
	// 读取具有无效字典的ZLIB数据时返回ErrDictionary。
	ErrDictionary = errors.New("zlib: invalid dictionary")
	// 读取具有无效标头的ZLIB数据时返回ErrHeader。
	ErrHeader = errors.New("zlib: invalid header")
)

type reader struct {
	r            flate.Reader
	decompressor io.ReadCloser
	digest       hash.Hash32
	err          error
	scratch      [4]byte
}

// 重置器重置NewReader或NewReaderDict返回的ReadCloser
// 切换到新的底层读取器。这允许重新使用ReadCloser
// 而不是分配一个新的。
type Resetter interface {
	// 重置将丢弃任何缓冲数据，并将重置器重置为
	// 使用给定的读取器新初始化。
	Reset(r io.Reader, dict []byte) error
}

// NewReader创建一个新的ReadCloser。
// 从返回的ReadCloser读取并从r解压缩数据。
// 如果r未实现io.ByteReader，则解压缩程序可能会读取更多
// 不必要的数据来自r。
// 完成后，调用方负责调用ReadCloser上的Close。
// None
// NewReader返回的ReadCloser还实现了重置。
func NewReader(r io.Reader) (io.ReadCloser, error) {
	return NewReaderDict(r, nil)
}

// NewReaderDict与NewReader类似，但使用预设词典。
// 如果压缩数据未引用字典，NewReaderDict将忽略字典。
// 如果压缩数据引用不同的字典，NewReaderDict将返回ErrDictionary。
// None
// NewReaderDict返回的ReadCloser也实现了重置。
func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
	z := new(reader)
	err := z.Reset(r, dict)
	if err != nil {
		return nil, err
	}
	return z, nil
}

func (z *reader) Read(p []byte) (int, error) {
	if z.err != nil {
		return 0, z.err
	}

	var n int
	n, z.err = z.decompressor.Read(p)
	z.digest.Write(p[0:n])
	if z.err != io.EOF {
		// 在正常情况下，我们回到这里。
		return n, z.err
	}

	// 完成文件；检查校验和。
	if _, err := io.ReadFull(z.r, z.scratch[0:4]); err != nil {
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
		z.err = err
		return n, z.err
	}
	// 与GZIP（RFC1952）不同，ZLIB（RFC1950）是大端的。
	checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
	if checksum != z.digest.Sum32() {
		z.err = ErrChecksum
		return n, z.err
	}
	return n, io.EOF
}

// 调用Close不会关闭最初传递给NewReader的包装io.Reader。
// 为了验证ZLIB校验和，必须检查读取器
// 完全消耗，直到io.EOF。
func (z *reader) Close() error {
	if z.err != nil && z.err != io.EOF {
		return z.err
	}
	z.err = z.decompressor.Close()
	return z.err
}

func (z *reader) Reset(r io.Reader, dict []byte) error {
	*z = reader{decompressor: z.decompressor}
	if fr, ok := r.(flate.Reader); ok {
		z.r = fr
	} else {
		z.r = bufio.NewReader(r)
	}

	// 阅读标题（RFC 1950第2.2节）。
	_, z.err = io.ReadFull(z.r, z.scratch[0:2])
	if z.err != nil {
		if z.err == io.EOF {
			z.err = io.ErrUnexpectedEOF
		}
		return z.err
	}
	h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
	if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) {
		z.err = ErrHeader
		return z.err
	}
	haveDict := z.scratch[1]&0x20 != 0
	if haveDict {
		_, z.err = io.ReadFull(z.r, z.scratch[0:4])
		if z.err != nil {
			if z.err == io.EOF {
				z.err = io.ErrUnexpectedEOF
			}
			return z.err
		}
		checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
		if checksum != adler32.Checksum(dict) {
			z.err = ErrDictionary
			return z.err
		}
	}

	if z.decompressor == nil {
		if haveDict {
			z.decompressor = flate.NewReaderDict(z.r, dict)
		} else {
			z.decompressor = flate.NewReader(z.r)
		}
	} else {
		z.decompressor.(flate.Resetter).Reset(z.r, dict)
	}
	z.digest = adler32.New()
	return nil
}
